import logging
import os
import time
from pathlib import Path
from flask import Flask, g
from flask_cors import CORS
from dotenv import load_dotenv
from frame.exception.ApiException import ApiException
from frame.util.ResponseUtil import ResponseUtil
import werkzeug.exceptions as http_exceptions
from config.app import get_config
from frame.base import cache, limiter


# 运行类
class RunBase():
    def create_app(self):
        # 先加载环境变量
        load_dotenv()  # 加载默认路径的.env文件

        # 应用初始化
        app = Flask(
            __name__,
            static_folder="public",  # 将静态文件夹改为 "public"
            static_url_path="/public"  # 静态资源 URL 前缀改为 "/public"
        )

        # 动态选择配置类
        config = get_config()
        # print(config.FRAME) # 调用案例

        app.config.from_object(config())
        app.config['JSON_AS_ASCII'] = False  # 关闭默认ASCII转义
        app.config['JSONIFY_MIMETYPE'] = 'application/json; charset=utf-8'  # 全局设置MIMETYPE
        app.json.ensure_ascii = False  # 解决编码问题
        CORS(app)  # 启用跨域访问

        # 初始化扩展（绑定到应用）
        cache.init_app(app)
        limiter.init_app(app)

        # 确保runtime目录存在
        runtime_dir = app.config.get('RUNTIME_DIR', 'runtime')
        os.makedirs(runtime_dir, exist_ok=True)

        # ----------------------------
        # 注册子应用蓝图
        # ----------------------------
        self.register_blueprints(app)

        # ----------------------------
        # 配置日志系统
        # ----------------------------
        self.configure_logging(app)

        # ----------------------------
        # 记录请求开始时间
        # ----------------------------
        @app.before_request
        def record_start_time():
            g.start_time = time.time()

        # ----------------------------
        # 计算响应时间
        # ----------------------------
        @app.after_request
        def calculate_response_time(response):
            g.response_time = time.time() - g.start_time
            return response

        # ----------------------------
        # 错误处理
        # ----------------------------
        @app.errorhandler(Exception)
        def handle_exception(e):
            # 处理自定义异常
            if isinstance(e, ApiException):
                return ResponseUtil.error(e.code, e.msg), 200

            # 处理 HTTP 异常
            if isinstance(e, http_exceptions.HTTPException):
                return ResponseUtil.error(e.code, e.description), 200

            # 其他未知异常
            return ResponseUtil.error(500, str(e)), 200

        return app

    def register_blueprints(self, app):
        import os
        import importlib

        # 获取当前文件所在目录的绝对路径
        current_dir = os.path.dirname(os.path.abspath(__file__))
        # 假设apps目录位于当前目录的上级目录中，根据实际情况调整路径
        apps_dir = os.path.join(os.path.dirname(os.path.dirname(current_dir)), 'apps')

        # 获取所有一级子目录，排除特殊目录
        sub_dirs = []
        for name in os.listdir(apps_dir):
            dir_path = os.path.join(apps_dir, name)
            if os.path.isdir(dir_path) and name not in ['__pycache__']:
                sub_dirs.append(name)

        # 遍历子目录并注册蓝图
        for subdir in sub_dirs:
            # 构造蓝图变量名，如 home_bp
            bp_name = f'{subdir}_bp'
            try:
                # 动态导入子应用模块，例如 apps.home
                module = importlib.import_module(f'apps.{subdir}')
                # 获取蓝图对象
                bp = getattr(module, bp_name)
                # 注册蓝图
                app.register_blueprint(bp)
            except ImportError as e:
                print(f"Error importing module {subdir}: {e}")
            except AttributeError:
                print(f"Blueprint {bp_name} not found in {subdir}")
            except Exception as e:
                print(f"Unexpected error registering {subdir}: {e}")

        # # 1. 导入子应用蓝图（此时子应用内部路由已绑定装饰器） TODO 需要实现自动注册功能
        # from apps.home import home_bp
        # from apps.crawler import crawler_bp
        # from apps.printer import printer_bp
        #
        # # 2. 注册蓝图到主应用
        # app.register_blueprint(home_bp)
        # app.register_blueprint(crawler_bp)
        # app.register_blueprint(printer_bp)

    def configure_logging(self, app):
        """集中配置日志系统 TODO 待完善"""
        # 禁用默认日志
        # logging.getLogger('werkzeug').disabled = True

        # 配置每个应用的日志
        for name, blueprint in app.blueprints.items():
            app_log_dir = Path(app.config['RUNTIME_DIR']) / name
            app_log_dir.mkdir(parents=True, exist_ok=True)
